#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <jpeglib.h>
#include <SDL2/SDL.h>
#include <SDL2/SDL_ttf.h>

// 窗口和显示常量
#define WINDOW_WIDTH 1024
#define WINDOW_HEIGHT 768
#define HISTOGRAM_WIDTH 768
#define HISTOGRAM_HEIGHT 600
#define BAR_WIDTH 3
#define FONT_SIZE 16
#define DEFAULT_SCALE_FACTOR 2000

/**
 * 生成JPEG图像的灰度直方图
 * @param filename JPEG文件路径
 * @param histogram 输出的直方图数组
 * @param image_info 输出的图像信息
 * @return 0成功，-1失败
 */
int generate_histogram(const char *filename, int histogram[256], struct {
    int width;
    int height;
    int components;
    int total_pixels;
} *image_info) {
    struct jpeg_decompress_struct cinfo;
    struct jpeg_error_mgr jerr;

    FILE *infile = fopen(filename, "rb");
    if (!infile) {
        fprintf(stderr, "错误: 无法打开文件 '%s'\n", filename);
        return -1;
    }

    // 设置错误处理
    cinfo.err = jpeg_std_error(&jerr);
    jpeg_create_decompress(&cinfo);
    jpeg_stdio_src(&cinfo, infile);
    
    // 读取JPEG头信息
    if (jpeg_read_header(&cinfo, TRUE) != JPEG_HEADER_OK) {
        fprintf(stderr, "错误: 无效的JPEG文件格式\n");
        fclose(infile);
        return -1;
    }
    
    // 强制输出为RGB格式
    cinfo.out_color_space = JCS_RGB;
    jpeg_start_decompress(&cinfo);

    int width = cinfo.output_width;
    int height = cinfo.output_height;
    int components = cinfo.output_components;
    
    // 保存图像信息
    if (image_info) {
        image_info->width = width;
        image_info->height = height;
        image_info->components = components;
        image_info->total_pixels = width * height;
    }
    
    printf("正在处理JPEG图像: %dx%d 像素, %d通道\n", width, height, components);
    
    // 分配行缓冲区
    unsigned char *buffer = (unsigned char *)malloc(width * components);
    if (!buffer) {
        fprintf(stderr, "错误: 内存分配失败\n");
        jpeg_finish_decompress(&cinfo);
        jpeg_destroy_decompress(&cinfo);
        fclose(infile);
        return -1;
    }
    
    // 读取像素数据并计算灰度直方图
    while (cinfo.output_scanline < height) {
        jpeg_read_scanlines(&cinfo, &buffer, 1);
        
        for (int x = 0; x < width; x++) {
            unsigned char gray;
            
            if (components == 3) {
                // RGB图像，使用标准加权平均
                unsigned char r = buffer[x * 3];
                unsigned char g = buffer[x * 3 + 1];
                unsigned char b = buffer[x * 3 + 2];
                gray = (unsigned char)(0.299 * r + 0.587 * g + 0.114 * b);
            } else if (components == 1) {
                // 灰度图像
                gray = buffer[x];
            } else {
                // 其他格式，使用简单平均
                int sum = 0;
                for (int c = 0; c < components; c++) {
                    sum += buffer[x * components + c];
                }
                gray = (unsigned char)(sum / components);
            }
            
            histogram[gray]++;
        }
    }

    // 清理资源
    free(buffer);
    jpeg_finish_decompress(&cinfo);
    jpeg_destroy_decompress(&cinfo);
    fclose(infile);
    
    return 0;
}

/**
 * 使用SDL绘制直方图
 * @param histogram 直方图数据
 * @param image_info 图像信息
 * @param scale_factor 缩放因子
 * @param show_time 显示时间（毫秒，0表示等待用户关闭）
 * @return 0成功，-1失败
 */
int draw_histogram(int histogram[256], const struct {
    int width;
    int height;
    int components;
    int total_pixels;
} *image_info, int scale_factor, int show_time) {
    
    // 初始化SDL
    if (SDL_Init(SDL_INIT_VIDEO) < 0) {
        fprintf(stderr, "SDL初始化失败: %s\n", SDL_GetError());
        return -1;
    }
    
    if (TTF_Init() == -1) {
        fprintf(stderr, "TTF初始化失败: %s\n", TTF_GetError());
        SDL_Quit();
        return -1;
    }
    
    // 创建窗口和渲染器
    SDL_Window *window = SDL_CreateWindow(
        "JPEG直方图分析器",
        SDL_WINDOWPOS_CENTERED,
        SDL_WINDOWPOS_CENTERED,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        SDL_WINDOW_SHOWN
    );
    
    if (!window) {
        fprintf(stderr, "窗口创建失败: %s\n", SDL_GetError());
        TTF_Quit();
        SDL_Quit();
        return -1;
    }
    
    SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
    if (!renderer) {
        fprintf(stderr, "渲染器创建失败: %s\n", SDL_GetError());
        SDL_DestroyWindow(window);
        TTF_Quit();
        SDL_Quit();
        return -1;
    }

    // 尝试加载字体
    TTF_Font *font = NULL;
    const char *font_paths[] = {
        "/System/Library/Fonts/Arial.ttf",  // macOS
        "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",  // Linux
        "C:/Windows/Fonts/arial.ttf",  // Windows
        "./fonts/arial.ttf",  // 本地字体目录
        NULL
    };
    
    for (int i = 0; font_paths[i] != NULL; i++) {
        font = TTF_OpenFont(font_paths[i], FONT_SIZE);
        if (font) {
            printf("使用字体: %s\n", font_paths[i]);
            break;
        }
    }
    
    if (!font) {
        printf("警告: 无法加载字体，将不显示文字标签\n");
    }
    
    // 找到最大值用于缩放
    int max_count = 0;
    for (int i = 0; i < 256; i++) {
        if (histogram[i] > max_count) {
            max_count = histogram[i];
        }
    }
    
    bool running = true;
    SDL_Event event;
    Uint32 start_time = SDL_GetTicks();
    
    printf("图形窗口已打开，按ESC键或关闭按钮退出\n");
    
    while (running) {
        // 处理事件
        while (SDL_PollEvent(&event)) {
            switch (event.type) {
                case SDL_QUIT:
                    running = false;
                    break;
                case SDL_KEYDOWN:
                    if (event.key.keysym.sym == SDLK_ESCAPE) {
                        running = false;
                    }
                    break;
            }
        }
        
        // 如果设置了显示时间且时间到了，自动退出
        if (show_time > 0 && (SDL_GetTicks() - start_time) > (Uint32)show_time) {
            running = false;
        }
        
        // 清空屏幕（白色背景）
        SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
        SDL_RenderClear(renderer);
        
        // 绘制标题和信息
        if (font && image_info) {
            SDL_Color black = {0, 0, 0, 255};
            char title[256];
            snprintf(title, sizeof(title), "JPEG直方图分析 - %dx%d像素, %d通道, 总像素: %d",
                    image_info->width, image_info->height, 
                    image_info->components, image_info->total_pixels);
            
            SDL_Surface *title_surface = TTF_RenderUTF8_Solid(font, title, black);
            if (title_surface) {
                SDL_Texture *title_texture = SDL_CreateTextureFromSurface(renderer, title_surface);
                SDL_Rect title_rect = {10, 10, title_surface->w, title_surface->h};
                SDL_RenderCopy(renderer, title_texture, NULL, &title_rect);
                SDL_FreeSurface(title_surface);
                SDL_DestroyTexture(title_texture);
            }
        }
        
        // 绘制直方图
        for (int i = 0; i < 256; i++) {
            if (histogram[i] > 0) {
                int bar_height = (histogram[i] * HISTOGRAM_HEIGHT) / (max_count > 0 ? max_count : 1);
                if (bar_height > HISTOGRAM_HEIGHT) bar_height = HISTOGRAM_HEIGHT;
                
                // 使用渐变色
                int color_intensity = (i * 255) / 255;
                SDL_SetRenderDrawColor(renderer, 255 - color_intensity, 0, color_intensity, 255);
                
                SDL_Rect rect = {
                    i * BAR_WIDTH + 10,
                    WINDOW_HEIGHT - 100 - bar_height,
                    BAR_WIDTH - 1,
                    bar_height
                };
                SDL_RenderFillRect(renderer, &rect);
            }
        }
        
        // 绘制坐标轴标签
        if (font) {
            SDL_Color black = {0, 0, 0, 255};
            for (int i = 0; i <= 255; i += 32) {
                char label[8];
                snprintf(label, sizeof(label), "%d", i);
                
                SDL_Surface *label_surface = TTF_RenderText_Solid(font, label, black);
                if (label_surface) {
                    SDL_Texture *label_texture = SDL_CreateTextureFromSurface(renderer, label_surface);
                    SDL_Rect label_rect = {
                        i * BAR_WIDTH + 5,
                        WINDOW_HEIGHT - 50,
                        label_surface->w,
                        label_surface->h
                    };
                    SDL_RenderCopy(renderer, label_texture, NULL, &label_rect);
                    SDL_FreeSurface(label_surface);
                    SDL_DestroyTexture(label_texture);
                }
            }
            
            // 显示操作提示
            const char *hint = "按ESC退出 | 关闭窗口退出";
            SDL_Surface *hint_surface = TTF_RenderUTF8_Solid(font, hint, black);
            if (hint_surface) {
                SDL_Texture *hint_texture = SDL_CreateTextureFromSurface(renderer, hint_surface);
                SDL_Rect hint_rect = {
                    WINDOW_WIDTH - hint_surface->w - 10,
                    WINDOW_HEIGHT - 30,
                    hint_surface->w,
                    hint_surface->h
                };
                SDL_RenderCopy(renderer, hint_texture, NULL, &hint_rect);
                SDL_FreeSurface(hint_surface);
                SDL_DestroyTexture(hint_texture);
            }
        }
        
        SDL_RenderPresent(renderer);
        SDL_Delay(16); // ~60 FPS
    }

    // 清理资源
    if (font) {
        TTF_CloseFont(font);
    }
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    TTF_Quit();
    SDL_Quit();
    
    return 0;
}

/**
 * 显示使用帮助信息
 */
void print_usage(const char *program_name) {
    printf("用法: %s <JPEG文件> [选项]\n", program_name);
    printf("选项:\n");
    printf("  -t <时间>    显示时间（毫秒，0表示等待用户关闭，默认: 0）\n");
    printf("  -s <数值>    直方图缩放因子（默认: %d）\n", DEFAULT_SCALE_FACTOR);
    printf("  -h          显示此帮助信息\n");
    printf("\n示例:\n");
    printf("  %s image.jpg\n", program_name);
    printf("  %s image.jpg -t 5000 -s 1000\n", program_name);
    printf("\n支持的格式:\n");
    printf("  - JPEG/JPG图像文件\n");
    printf("  - RGB和灰度图像\n");
    printf("\n操作说明:\n");
    printf("  - 按ESC键退出\n");
    printf("  - 点击窗口关闭按钮退出\n");
}

int main(int argc, char *argv[]) {
    if (argc < 2) {
        print_usage(argv[0]);
        return 1;
    }
    
    const char *filename = argv[1];
    int scale_factor = DEFAULT_SCALE_FACTOR;
    int show_time = 0; // 0表示等待用户关闭
    
    // 解析命令行参数
    for (int i = 2; i < argc; i++) {
        if (strcmp(argv[i], "-h") == 0) {
            print_usage(argv[0]);
            return 0;
        } else if (strcmp(argv[i], "-s") == 0 && i + 1 < argc) {
            scale_factor = atoi(argv[++i]);
            if (scale_factor <= 0) {
                fprintf(stderr, "错误: 缩放因子必须为正数\n");
                return 1;
            }
        } else if (strcmp(argv[i], "-t") == 0 && i + 1 < argc) {
            show_time = atoi(argv[++i]);
            if (show_time < 0) {
                fprintf(stderr, "错误: 显示时间不能为负数\n");
                return 1;
            }
        } else {
            fprintf(stderr, "错误: 未知参数 '%s'\n", argv[i]);
            print_usage(argv[0]);
            return 1;
        }
    }
    
    // 检查文件是否存在
    FILE *test_file = fopen(filename, "rb");
    if (!test_file) {
        fprintf(stderr, "错误: 文件 '%s' 不存在或无法访问\n", filename);
        return 1;
    }
    fclose(test_file);
    
    printf("开始分析JPEG文件: %s\n", filename);
    
    // 生成直方图
    int histogram[256] = {0};
    struct {
        int width;
        int height;
        int components;
        int total_pixels;
    } image_info;
    
    if (generate_histogram(filename, histogram, &image_info) != 0) {
        fprintf(stderr, "错误: 无法生成直方图\n");
        return 1;
    }
    
    printf("直方图生成完成，正在启动图形界面...\n");
    
    // 显示直方图
    if (draw_histogram(histogram, &image_info, scale_factor, show_time) != 0) {
        fprintf(stderr, "错误: 无法显示直方图\n");
        return 1;
    }
    
    printf("程序退出\n");
    return 0;
}

/*
 * 编译说明:
 * 
 * 基本编译:
 * gcc jpg_histogram_sdl.c -o jpg_histogram_sdl -ljpeg -lSDL2 -lSDL2_ttf
 * 
 * 带调试信息:
 * gcc -g -Wall jpg_histogram_sdl.c -o jpg_histogram_sdl -ljpeg -lSDL2 -lSDL2_ttf
 * 
 * 依赖库安装:
 * Ubuntu/Debian:
 *   sudo apt-get install libjpeg-dev libsdl2-dev libsdl2-ttf-dev
 * 
 * CentOS/RHEL:
 *   sudo yum install libjpeg-devel SDL2-devel SDL2_ttf-devel
 * 
 * macOS:
 *   brew install jpeg sdl2 sdl2_ttf
 * 
 * Windows (MSYS2):
 *   pacman -S mingw-w64-x86_64-libjpeg-turbo mingw-w64-x86_64-SDL2 mingw-w64-x86_64-SDL2_ttf
 */